﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace AnalysisEnvironment.PackageProviders.Business
{
    public class LocalFilePackageProvider : IPackageProvider
    {
        public string ProjectPath { get; set; }

        //Dictionary<string, List<string>> AllAssemblyNames = new Dictionary<string, List<string>>();

        public LocalFilePackageProvider(string path)
        {
            ProjectPath = path;

            //var files = Directory.GetFiles(path);

            //var suffixs = new[] { ".dll", ".exe" };

            //foreach (var file in files)
            //{
            //    if (suffixs.Any(n => file.EndsWith(n, StringComparison.OrdinalIgnoreCase)) != true)
            //        continue;

            //    try
            //    {
            //        var itemName = AssemblyName.GetAssemblyName(file);
            //        if (itemName == null)
            //            continue;

            //        if (AllAssemblyNames.TryGetValue(itemName.Name, out var list) != true)
            //        {
            //            list = new List<string>();
            //            AllAssemblyNames[itemName.Name] = list;
            //        }

            //        list.Add(file);
            //    }
            //    catch (Exception ex)
            //    {
            //        Console.WriteLine($"尝试加载程序集 {file} 时出错 {ex}");
            //    }
            //}
        }

        //public List<AssemblyName> SearchAssembly(AssemblyName name)
        //{
        //    if (AllAssemblyNames.TryGetValue(name.Name, out var files) != true)
        //        return null;

        //    return files.Select(f => AssemblyName.GetAssemblyName(f)).ToList();
        //}

        public Assembly TryLoadAssembly(AssemblyName name)
        {
            //if (AllAssemblyNames.TryGetValue(name.Name, out var files) != true)
            //    return null;

            //return FindMustMatchFile(name, files);

            var searchNames = new[]
            {
                $"{name.Name}.dll",
                $"{name.Name}.exe",
            };

            foreach (var item in searchNames)
            {
                var filePath = Path.Combine(ProjectPath, item);
                if (File.Exists(filePath) != true)
                    continue;

                return Assembly.LoadFrom(filePath);
            }

            return null;
        }

        public static Assembly FindMustMatchFile(AssemblyName name, List<string> files)
        {
            if (files?.Any() != true)
                return null;

            // 版本号，文件名
            var infos = new List<Tuple<int, string>>();

            foreach (var file in files)
            {
                var fileAssemblyName = AssemblyName.GetAssemblyName(file);

                // 名称不匹配
                if (fileAssemblyName.Name != name.Name)
                    continue;

                // 版本号正好相等则直接取这个版本
                if (fileAssemblyName.Version == name.Version)
                    return Assembly.Load(file);

                // 版本号对不上
                if (fileAssemblyName.Version.GetHashCode() < name.Version.GetHashCode())
                    continue;


                infos.Add(new Tuple<int, string>(fileAssemblyName.Version.GetHashCode(), file));
            }

            if (infos?.Any() != true)
                return null;

            // 没有完全匹配的就取最新的
            var mustMatchFile = infos.OrderByDescending(f => f.Item1).First().Item2;

            return Assembly.LoadFile(mustMatchFile);
        }
    }
}
